home *** CD-ROM | disk | FTP | other *** search
- /* +-------------------------------------------------------------------+ */
- /* | Copyright 1993, David Koblas (koblas@netcom.com) | */
- /* | | */
- /* | Permission to use, copy, modify, and to distribute this software | */
- /* | and its documentation for any purpose is hereby granted without | */
- /* | fee, provided that the above copyright notice appear in all | */
- /* | copies and that both that copyright notice and this permission | */
- /* | notice appear in supporting documentation. There is no | */
- /* | representations about the suitability of this software for | */
- /* | any purpose. this software is provided "as is" without express | */
- /* | or implied warranty. | */
- /* | | */
- /* +-------------------------------------------------------------------+ */
-
- #include <X11/Intrinsic.h>
- #include <X11/StringDefs.h>
- #include <X11/Xatom.h>
- #include <X11/cursorfont.h>
- #include <sys/time.h>
-
- extern XImage *NewXImage(Display*,Visual*,int,int,int);
-
- typedef void (*func_t)(Widget, void *, XEvent *);
-
- typedef struct li_s {
- /*
- ** Destroy request info
- */
- void *data;
- func_t func;
-
- /*
- ** Info for watch cursor
- */
- int watchCount, computingCount;
- Widget shell, parent;
- Window win;
- Display *dpy;
- struct li_s *next;
- } LocalInfo;
-
- #define DO_MAP(l) ((l)->watchCount + (l)->computingCount > 0)
-
- #include "bitmaps/wait1.xbm"
- #include "bitmaps/wait2.xbm"
- #include "bitmaps/wait3.xbm"
- #include "bitmaps/wait4.xbm"
-
- static Atom delwin = None, protocols = None;
- static LocalInfo *head = NULL;
-
- static int currentCursor = 0;
- static Cursor watchCursor = None;
-
- static struct {
- Cursor cursor;
- int width, height;
- unsigned char *bits;
- } cursorInfo[] = {
- { None, wait1_width, wait1_height, wait1_bits },
- { None, wait2_width, wait2_height, wait2_bits },
- { None, wait3_width, wait3_height, wait3_bits },
- { None, wait4_width, wait4_height, wait4_bits },
- };
-
- static void initCursors(Widget w)
- {
- static int inited = False;
- Display *dpy = XtDisplay(w);
- Screen *screen = XtScreen(w);
- GC gc = None;
- Pixmap pix, mask;
- int i, width, height;
- XImage *src, *msk;
- int x, y;
- XColor xcols[2];
-
- if (inited)
- return;
- inited = True;
-
- xcols[0].pixel = BlackPixelOfScreen(screen);
- xcols[1].pixel = WhitePixelOfScreen(screen);
-
- XQueryColors(dpy, DefaultColormapOfScreen(screen), xcols, XtNumber(xcols));
-
- for (i = 0; i < XtNumber(cursorInfo); i++) {
- width = cursorInfo[i].width;
- height = cursorInfo[i].height;
- pix = XCreatePixmapFromBitmapData(dpy, RootWindowOfScreen(screen),
- (char*)cursorInfo[i].bits, width, height, True, False, 1);
- src = XGetImage(dpy, pix, 0, 0, width, height, AllPlanes, ZPixmap);
- msk = NewXImage(dpy, NULL, 1, width, height);
- for (y = 0; y < height; y++) {
- for (x = 0; x < width; x++) {
- Boolean flg = (Boolean)XGetPixel(src, x, y);
-
- if (!flg && x > 0)
- flg = XGetPixel(src, x - 1, y);
- if (!flg && x < width - 1)
- flg = XGetPixel(src, x + 1, y);
- if (!flg && y > 0)
- flg = XGetPixel(src, x, y - 1);
- if (!flg && y < height - 1)
- flg = XGetPixel(src, x, y + 1);
- XPutPixel(msk, x, y, flg);
- }
- }
-
- mask = XCreatePixmap(dpy, pix, width, height, 1);
- if (gc == None)
- gc = XCreateGC(dpy, mask, 0, 0);
- XPutImage(dpy, mask, gc, msk, 0, 0, 0, 0, width, height);
-
- XDestroyImage(src);
- XDestroyImage(msk);
-
- cursorInfo[i].cursor = XCreatePixmapCursor(dpy, pix, mask,
- &xcols[0], &xcols[1], width / 2, height / 2);
- XFreePixmap(dpy, pix);
- XFreePixmap(dpy, mask);
- }
- if (gc != None)
- XFreeGC(dpy, gc);
- }
-
- static void destroyCallback(Widget w, XtPointer data, XtPointer junk)
- {
- LocalInfo *l = (LocalInfo *)data;
- LocalInfo *cur, **pp;
-
- for (cur = *(pp = &head); cur != NULL && cur != l; cur = *(pp = &cur->next));
-
- if (cur == NULL)
- return;
-
- *pp = cur->next;
-
- XtFree((XtPointer)data);
- }
-
- static void handler(Widget w, XtPointer lArg, XEvent *eventArg, Boolean *junk)
- {
- XClientMessageEvent *event = (XClientMessageEvent*)eventArg;
- LocalInfo *l = (LocalInfo *)lArg;
- if (event->type != ClientMessage)
- return;
-
- if (event->message_type == protocols && event->data.l[0] == delwin)
- l->func(w, l->data, eventArg);
- }
-
- static void add(Widget w, LocalInfo *l)
- {
- unsigned long valuemask;
- XSetWindowAttributes attributes;
- /*
- ** Set up the shell destroy info
- */
- XtAddRawEventHandler(w, 0, True, handler, (XtPointer)l);
- XChangeProperty(XtDisplay(w), XtWindow(w), protocols,
- XA_ATOM, 32, PropModeReplace,
- (unsigned char *) &delwin, 1);
-
- /*
- ** Now set up watch cursor information
- **
- ** Ignore device events while the busy cursor is displayed.
- */
- valuemask = CWDontPropagate | CWCursor;
- attributes.do_not_propagate_mask = (KeyPressMask | KeyReleaseMask |
- ButtonPressMask | ButtonReleaseMask | PointerMotionMask);
- if (watchCursor == None)
- watchCursor = XCreateFontCursor(XtDisplay(w), XC_watch);
- attributes.cursor = watchCursor;
-
- /*
- ** The window will be as big as the display screen, and clipped by
- ** its own parent window, so we never have to worry about resizing
- */
- l->win = XCreateWindow(XtDisplay(w), XtWindow(w), 0, 0,
- WidthOfScreen(XtScreen(w)), HeightOfScreen(XtScreen(w)),
- (unsigned int) 0, 0, InputOnly,
- CopyFromParent, valuemask, &attributes);
-
- if (DO_MAP(l))
- XMapRaised(l->dpy, l->win);
- }
-
-
- static void realize(Widget w, XtPointer ldataArg, XEvent *event, Boolean *junk)
- {
- if (event->type == MapNotify) {
- XtRemoveEventHandler(w, StructureNotifyMask, False,
- realize, ldataArg);
- add(w, (LocalInfo*)ldataArg);
- }
- }
-
- void AddDestroyCallback(Widget w, func_t func, void *data)
- {
- LocalInfo *l;
-
- if (delwin == None)
- delwin = XInternAtom(XtDisplay(w), "WM_DELETE_WINDOW", FALSE);
- if (protocols == None)
- protocols = XInternAtom(XtDisplay(w), "WM_PROTOCOLS", FALSE);
-
- initCursors(w);
-
- if (delwin == None || protocols == None)
- return;
-
- l = XtNew(LocalInfo);
- l->data = data;
- l->func = func;
- l->win = None;
- l->dpy = XtDisplay(w);
- l->watchCount = 0;
- l->computingCount = 0;
- l->shell = w;
- l->parent = None;
-
- if (!XtIsRealized(w))
- XtAddEventHandler(w, StructureNotifyMask, False, realize, (XtPointer)l);
- else
- add(w, l);
-
- XtAddCallback(w, XtNdestroyCallback, destroyCallback, (XtPointer)l);
-
- l->next = head;
- head = l;
- }
-
- static Boolean setBusy(LocalInfo *cur, Boolean isWatch, Boolean flag)
- {
- Boolean doFlush = False;
-
- if (isWatch) {
- if (flag) {
- cur->watchCount++;
- } else {
- if (cur->watchCount == 0)
- return False;
- cur->watchCount--;
- }
- } else {
- if (flag) {
- cur->computingCount++;
- } else {
- if (cur->computingCount == 0)
- return False;
- cur->computingCount--;
- }
- }
-
- if (cur->win == None)
- return False;
-
- if (cur->watchCount == 0 && cur->computingCount == 0) {
- XUnmapWindow(cur->dpy, cur->win);
- return False;
- }
-
- if (cur->watchCount == 1) {
- if (isWatch) {
- XMapRaised(cur->dpy, cur->win);
- XDefineCursor(cur->dpy, cur->win, watchCursor);
- doFlush = True;
- }
- } else if (cur->computingCount == 1) {
- if (!isWatch) {
- XMapRaised(cur->dpy, cur->win);
- XDefineCursor(cur->dpy, cur->win, cursorInfo[currentCursor].cursor);
- doFlush = True;
- }
- }
-
- return doFlush;
- }
-
- void StateSetBusyWatch(Boolean flag)
- {
- LocalInfo *cur;
- Boolean doFlush = False;
-
- for (cur = head; cur != NULL; cur = cur->next)
- doFlush |= setBusy(cur, True, flag);
-
- if (doFlush)
- XFlush(head->dpy);
- }
-
- void StateSetBusy(Boolean flag)
- {
- LocalInfo *cur;
- Boolean doFlush = False;
-
- for (cur = head; cur != NULL; cur = cur->next)
- doFlush |= setBusy(cur, False, flag);
-
- if (doFlush)
- XFlush(head->dpy);
- }
-
- void StateShellBusy(Widget w, Boolean flag)
- {
- LocalInfo *cur;
- Boolean doFlush = False;
-
- if (w == None)
- return;
-
- while (!XtIsShell(w))
- w = XtParent(w);
-
- for (cur = head; cur != NULL; cur = cur->next) {
- if (cur->shell == w) {
- doFlush |= setBusy(cur, True, flag);
- } else if (cur->parent == w) {
- StateShellBusy(cur->shell, flag);
- }
- }
- if (doFlush)
- XFlush(head->dpy);
- }
-
- void StateAddParent(Widget w, Widget parent)
- {
- LocalInfo *cur;
-
- if (w == None || parent == None)
- return;
-
- while (!XtIsShell(parent))
- parent = XtParent(parent);
- while (!XtIsShell(w))
- w = XtParent(w);
-
- for (cur = head; cur != NULL && cur->shell != w; cur = cur->next)
- ;
- if (cur == NULL)
- return;
-
- cur->parent = parent;
- }
-
- void StateTimeStep()
- {
- static Boolean inited = False;
- static struct timeval lastTime;
- struct timeval nowTime;
- Boolean done = False, need = False;
- Cursor c;
- LocalInfo *cur;
-
- for (cur = head; cur != NULL; cur = cur->next)
- if (cur->watchCount == 0 && cur->computingCount != 0 && cur->win != None)
- need = True;
-
- if (!need)
- return;
-
- gettimeofday(&nowTime, NULL);
- if (inited) {
- long ds, dus;
-
- dus = nowTime.tv_usec - lastTime.tv_usec;
- ds = nowTime.tv_sec - lastTime.tv_sec;
- if (dus < 0) {
- ds--;
- dus += 1000000;
- }
- if (ds == 0 && dus < 200000)
- return;
- } else {
- inited = True;
- }
- lastTime = nowTime;
-
-
- if (++currentCursor == XtNumber(cursorInfo))
- currentCursor = 0;
-
- c = cursorInfo[currentCursor].cursor;
-
- for (cur = head; cur != NULL; cur = cur->next) {
- if (cur->watchCount == 0 && cur->computingCount != 0 && cur->win != None) {
- XDefineCursor(cur->dpy, cur->win, c);
- done = True;
- }
- }
-
- if (done)
- XFlush(head->dpy);
- }
-